"use strict";
// interface Named {
//   name: string
// }
// class Person {
//   name: string
// }
// let p: Named
// p = new Person()
// interface Named {
//   name: string
// }
// let x: Named
// let y = { name: 'Alice', location: 'Seattle' }
// x = y
// function greet(n: Named) {
//   console.log('Hello, ' + n.name)
// } 
// greet(y)
// 比较两个函数
// let x = (a: number) => 0
// let y = (b: number, s: string) => 0
// y = x
// x = y // Error
// let x = () => ({ name: 'Alice' })
// let y = () => ({ name: 'Alice', location: 'Seattle' })
// x = y
// y = x
// 枚举
// enum Status { Ready, Waiting }
// enum Color { Red, Bule, Green }
// let status1 = Status.Ready
// status1 = Color.Green // 报错，不能将类型“Color.Green”分配给类型“Status”
// 类
// class Animal {
//   feet: number
//   constructor(name: string, numFeet: number) {}
// }
// class Size {
//   feet: number
//   constructor(numFeet: number) {}
// }
// let a: Animal
// let s: Size
// a = s
// s = a
// 泛型
// interface Empty<T> {
// }
// let x: Empty<number>
// let y: Empty<number>
// x = y
// interface Empty<T> {
//   data: T
// }
// let x: Empty<number>
// let y: Empty<string>
// x = y // 报错
// 高级类型
// 交叉类型
// function extend<T, U>(first: T, second: U): T & U {
//   let result = <T & U>{}
//   for (let id in first) {
//     (<any>result)[id] = (<any>first)[id]
//   }
//   for (let id in second) {
//     if (!result.hasOwnProperty(id)) {
//       (<any>result)[id] = (<any>second)[id]
//     }
//   }
//   return result
// }
// class Person {
//   constructor(public name: string) {}
// }
// interface Loggable {
//   log(): void
// }
// class ConsoleLogger implements Loggable {
//   log() {
//   }
// }
// var jim = extend(new Person('Jim'), new ConsoleLogger())
// var n = jim.name
// jim.log()
// 联合类型
// 一个代码库希望传入 number 或 string 类型的参数
// function padLeft(value: string, padding: any) {
//   if (typeof padding === 'number') {
//     return Array(padding + 1).join(' ') + value
//   }
//   if (typeof padding === 'string') {
//     return padding + value
//   }
//   throw new Error(`Expected string or number, got '${padding}'`)
// }
// console.log(padLeft('Hello World', 4)) // returns "    Hello world"
// console.log(padLeft('Hello World', true))
// 联合类型
// function padLeft(value: string, padding: string | number) {
//   if (typeof padding === 'number') {
//     return Array(padding + 1).join(' ') + value
//   }
//   if (typeof padding === 'string') {
//     return padding + value
//   }
//   throw new Error(`Expected string or number, got '${padding}'`)
// }
// console.log(padLeft('Hello World', true)) // 报错，类型“boolean”的参数不能赋给类型“string | number”的参数
// interface Bird {
//   fly()
//   layEggs()
// }
// interface Fish {
//   swim()
//   layEggs()
// }
// function getSmallPet(): Fish | Bird {
// }
// let pet = getSmallPet()
// pet.layEggs()
// pet.swim() // 报错，类型“Bird | Fish”上不存在属性“swim”。类型“Bird”上不存在属性“swim”。
// 类型断言
// if ((<Fish>pet).swim) {
//   (<Fish>pet).swim()
// } else {
//   (<Bird>pet).fly()
// }
// function isFish(pet: Fish | Bird): pet is Fish {
//   return (<Fish>pet).swim !== undefined
// }
// if (isFish(pet)) {
//   pet.swim()
// } else {
//   pet.fly()
// }
// function isNumber(x: any): x is number {
//   return typeof x === 'number'
// }
// function isString(x: any): x is string {
//   return typeof x === 'string'
// }
// function padLeft(value: string, padding: string | number) {
//   if (isNumber(padding)) {
//     return Array(padding + 1).join(' ') + value
//   }
//   if (isString(padding)) {
//     return padding + value
//   }
//   throw new Error(`Expected string or number, got '${padding}'.`)
// }
// typeof 类型保护
// function padLeft(value: string, padding: string | number) {
//   if (typeof padding === 'number') {
//     return Array(padding + 1).join(' ') + value
//   }
//   if (typeof padding === 'string') {
//     return padding + value
//   }
//   throw new Error(`Expected string or number, got '${padding}'.`)
// }
// instanceof 类型保护
// interface Padder {
//   getPaddingString(): string
// }
// class SpaceRepeatingPadder implements Padder {
//   constructor(private numSpaces: number) {}
//   getPaddingString() {
//     return Array(this.numSpaces + 1).join(' ')
//   }
// }
// class StringPadder implements Padder {
//   constructor(private value: string) {}
//   getPaddingString() {
//     return this.value
//   }
// }
// function getRandomPadder() {
//   return Math.random() < 0.5 ?
//     new SpaceRepeatingPadder(4) :
//     new StringPadder('  ')
// }
// // 类型为SpaceRepeatingPadder | StringPadder
// let padder: Padder = getRandomPadder()
// if (padder instanceof SpaceRepeatingPadder) {
//   padder // 类型细化为'SpaceRepeatingPadder'
// }
// if (padder instanceof StringPadder) {
//   padder // 类型细化为'StringPadder'
// }
// function f(sn: string | null): string {
//   if (sn === null) {
//     return 'default'
//   } else {
//     return sn
//   }
// }
// function f(sn: string | null): string {
//   return sn || 'default'
// }
// function broken(name: string | null): string {
//   function postfix(epithet: string) {
//     return name.charAt(0) + '. the ' + epithet
//   }
//   name = name || 'Bob'
//   return postfix('great')
// }
// function fixed(name: string | null): string {
//   function postfix(epithet: string) {
//     return name!.charAt(0) + '. the ' + epithet
//   }
//   name = name || 'Bob'
//   return postfix('great')
// }
// 类型别名
// type Name = string
// type NameResolver = () => string
// type NameOrResolver = Name | NameResolver
// function getName(n: NameOrResolver): Name {
//   if (typeof n === 'string') {
//     return n
//   } else {
//     return n()
//   }
// }
// type Container<T> = { value: T }
// type Tree<T> = {
//   value: T
//   left: Tree<T>
//   right: Tree<T>
// }
// type LinkedList<T> = T & { next: LinkedList<T> }
// interface Person {
//   name: string
// }
// var people: LinkedList<Person>
// var s = people.name
// var s = people.next.name
// var s = people.next.next.name
// var s = people.next.next.next.name
// 接口 vs 类型别名
// type Alias = { num: number }
// interface Interface {
//   num: number
// }
// declare function aliased(arg: Alias): Alias
// declare function interfaced(arg: Interface): Interface
// function createElement(tagName: 'img'): HTMLImageElement
// function createElement(tagName: 'input'):HTMLInputElement
// function createElement(tagName: string): Element {}
// interface Map<T> {
//   [key: string]: T
// }
// let keys: keyof Map<number>
// let value: Map<number>['foo']
// interface PersonPartial {
//   name?: string
//   age?: number
// }
// interface PersonReadonly {
//   readonly name: string
//   readonly age: number
// }
// type Readonlys<T> = {
//   readonly [P in keyof T]: T[P]
// }
// type Partials<T> = {
//   [P in keyof T]?: T[P]
// }
// Symbol
// let sym1 = Symbol()
// let sym2 = Symbol('key')
// let sym3 = Symbol('key')
// console.log(sym2 === sym3)
// let sym = Symbol()
// let obj = {
//   [sym]: 'value'
// }
// console.log(obj[sym])
// const getClassNameSymbol = Symbol()
// class C {
//   [getClassNameSymbol]() {
//     return 'c'
//   }
// }
// let c = new C()
// let className = c[getClassNameSymbol]
// console.log(className()) // 'c'
// let arr = [1, 'string', false]
// for (let i of arr) {
//   console.log(i) // 1 'string' false
// }
// for (let i in arr) {
//   console.log(i) // 0 1 2
// }
let pets = new Set(['Cat', 'Dog', 'Hamster']);
pets['species'] = 'mammals';
for (let pet in pets) {
    console.log(pet);
}
for (let pet of pets) {
    console.log(pet);
}
